import * as Joi from 'joi';

/**
 * 应用配置验证模式
 */
export const appConfigSchema = Joi.object({
  app: Joi.object({
    name: Joi.string().min(1).max(100).required(),
    version: Joi.string()
      .pattern(/^\d+\.\d+\.\d+$/)
      .required(),
    port: Joi.number().port().required(),
    environment: Joi.string()
      .valid('development', 'production', 'test')
      .required(),
    timezone: Joi.string().required(),
    appKey: Joi.string().min(8).required(),
    defaultLanguage: Joi.string().length(5).required(),
    supportedLocales: Joi.array()
      .items(Joi.string().length(5))
      .min(1)
      .required(),
  }).required(),

  database: Joi.object({
    host: Joi.string().hostname().required(),
    port: Joi.number().port().required(),
    username: Joi.string().min(1).required(),
    password: Joi.string().required(),
    database: Joi.string().min(1).required(),
    synchronize: Joi.boolean().required(),
    logging: Joi.boolean().required(),
    connectionLimit: Joi.number().min(1).max(100).required(),
    acquireTimeout: Joi.number().min(1000).max(300000).required(),
    timeout: Joi.number().min(1000).max(300000).required(),
    cacheDurationMs: Joi.number().min(1000).max(300000).required(),
    timezone: Joi.string().required(),
    charset: Joi.string().required(),
  }).required(),

  redis: Joi.object({
    host: Joi.string().hostname().required(),
    port: Joi.number().port().required(),
    password: Joi.string().allow('').required(),
    db: Joi.number().min(0).max(15).required(),
    keyPrefix: Joi.string().required(),
  }).required(),

  kafka: Joi.object({
    clientId: Joi.string().min(1).required(),
    brokers: Joi.array()
      .items(Joi.string().pattern(/^[a-zA-Z0-9.-]+:\d+$/))
      .min(1)
      .required(),
    groupId: Joi.string().min(1).required(),
    topicPrefix: Joi.string().required(),
  }).required(),

  jwt: Joi.object({
    secret: Joi.string().min(32).required(),
    expiresIn: Joi.string().required(),
    algorithm: Joi.string().valid('HS256', 'HS384', 'HS512').required(),
  }).required(),

  cache: Joi.object({
    ttl: Joi.number().min(1).max(86400).required(),
    maxItems: Joi.number().min(1).max(10000).required(),
    prefix: Joi.string().required(),
  }).required(),

  logging: Joi.object({
    level: Joi.string()
      .valid('error', 'warn', 'info', 'debug', 'verbose')
      .required(),
    format: Joi.string().valid('json', 'simple').required(),
    filename: Joi.string().optional(),
  }).required(),

  upload: Joi.object({
    path: Joi.string().required(),
    maxSize: Joi.number()
      .min(1024)
      .max(100 * 1024 * 1024)
      .required(),
    allowedTypes: Joi.array().items(Joi.string()).min(1).required(),
  }).required(),

  throttle: Joi.object({
    ttl: Joi.number().min(1).max(3600).required(),
    limit: Joi.number().min(1).max(10000).required(),
  }).required(),

  health: Joi.object({
    startupCheckEnabled: Joi.boolean().required(),
    startupTimeoutMs: Joi.number().min(1000).max(60000).required(),
  }).required(),

  swagger: Joi.object({
    enabled: Joi.boolean().required(),
    title: Joi.string().min(1).required(),
    description: Joi.string().min(1).required(),
    version: Joi.string()
      .pattern(/^\d+\.\d+\.\d+$/)
      .required(),
    auth: Joi.object({
      enabled: Joi.boolean().required(),
    }).required(),
    token: Joi.string().allow('').required(),
  }).required(),
});

/**
 * 验证应用配置
 */
export function validateAppConfig(config: Record<string, any>) {
  const { error, value } = appConfigSchema.validate(config, {
    allowUnknown: false,
    stripUnknown: true,
  });

  if (error) {
    throw new Error(
      `配置验证失败: ${error.details.map((d) => d.message).join(', ')}`,
    );
  }

  return value;
}
